Skip to main content

Chapter 28 - Terraform Modules - Existing

Using modules from the Terraform Registry

Modules are a collection of resource that are built together. These are the main way to package and reuse configurations in Terraform.

The root module can call child modules.

You can include modules from the local filesystem or from public or private repositories.

Use Public Modules


Git Repo 49 is used here.

In production, always lock the module version To implement a vnet module from the registry, such as: https://registry.terraform.io/modules/Azure/vnet/azurerm/latest

From the Terraform registry, you should be able to find any module and include that module using the block that is highlighted on the Module Registry page.

image.png

Note: Ctrl+Space does not work in modules. You would need to define the inputs from the Terraform Registry. Sometimes, there are examples you can copy. I copied and modified those below:

module "vnet_1" {
source = "Azure/vnet/azurerm"
version = "4.0.0" #always lock version in production
vnet_name = local.vnet_name
resource_group_name = azurerm_resource_group.rg_1.name
address_space = ["10.0.0.0/16"]
subnet_prefixes = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
subnet_names = ["subnet01", "subnet02", "subnet03"]
subnet_service_endpoints = {
subnet02 = ["Microsoft.Storage", "Microsoft.Sql"],
subnet03 = ["Microsoft.AzureActiveDirectory"]
}
tags = {
environment = "dev"
region = "centralus"
id = "123"
}
depends_on = [azurerm_resource_group.rg_1]
}

You can now create the normal resources such as public IP or NIC below this in the .tf file for the networking code.

Referencing the module in your new code is done as follows:

resource "azurerm_network_interface" "mynic" {
name = local.nic_name
location = azurerm_resource_group.myrg.location
resource_group_name = azurerm_resource_group.myrg.name

ip_configuration {
name = "internal"
subnet_id = module.vnet.vnet_subnets[0] ## here
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.mypublicip.id
}
tags = local.common_tags
}

Module Outputs


You can define the values as below, note the top one is not from a module, and the bottom two are.

# VM
output "vm_public_ip_address" {
description = "My Virtual Machine Public IP"
value = azurerm_linux_virtual_machine.mylinuxvm.public_ip_address
}

# VNet Name
# virtual_network_name
output "virtual_network_name" {
description = "Virtual Network Name"
value = module.vnet.vnet_name
}
# VNet ID
output "virtual_network_id" {
description = "Virtual Network ID"
value = module.vnet.vnet_id
}

Init, Validate, Plan, and Apply


When you run a terraform init on the dir with the modules, TF will download the modules and create a couple of key things:

  • modules dir
  • modules.json

Results of the terraform init:
image.png

Files created:
image.png

From here, run your sequence of Validate, Plan and Apply Run a terraform state list to see how these module resources look differently from the normal resources.

Tainting Module


You cannot taint an entire module, you must taint individual resources.

terraform state list
terraform taint module.vnet.vnet

Meta Arguments


You can still use meta arguments within modules:

  • count
  • for_each
  • providers
  • depends_on
  • lifecycle

Note about Module Sources


https://developer.hashicorp.com/terraform/language/modules/sources

  • local paths
  • github
  • bitbucket
  • S3 buckets